package com.woniu.zsd.merchant.config;

import cn.hutool.json.JSONUtil;
import com.woniu.client.PermissionClient;
import com.woniu.client.UserClient;
import com.woniu.form.ChatMessage;
import com.woniu.commons.util.RedisKey;
import com.woniu.zsd.commons.exception.ZsdException;
import com.woniu.zsd.merchant.util.MerchartTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class MessageHandler extends AbstractWebSocketHandler {
	@Resource
	private StringRedisTemplate stringRedisTemplate;

	private ConcurrentHashMap<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

	@Autowired
    private MerchartTokenUtil tokenUtil;

	@Autowired
	private UserClient userClient;

	@Autowired
	private PermissionClient permissionClient;

	/**
	 * ps：连接关闭执行该方法
	 */
	@Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
		//session就是中断的连接对象
		System.out.println("连接关闭，关闭原因:"+status.getReason());
	}
	/**
	 * ps：连接异常中断执行该方法
	 */
	@Override
	public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
		//session就是中断的连接对象
		String id = session.getAttributes().get("id").toString();
		sessions.remove(id);
		System.out.println("连接异常中断,中断原因:"+exception.getMessage());
	}
	/**
	 * ps：当客户端与服务器成功建立连接会执行该方法
	 */
	@Override
	public void afterConnectionEstablished(WebSocketSession session) throws Exception {
		String token = session.getUri().getQuery().split("=")[1];
		System.out.println(token);
		String adminId = null;
		String userId = null;
		if (stringRedisTemplate.hasKey(RedisKey.USER_REFRESH_TOKEN_KEY(token))){
			userId = tokenUtil.getUserId(token).toString();
			sessions.put(userId, session);
			System.out.println("连接成功,连接对象为用户:" + session);
		} else {
			adminId = tokenUtil.getAdminId(token).toString();
			sessions.put(adminId, session);
			System.out.println("连接成功,连接对象为管理员:" + session);
		}
	}
	/**
	 * ps:服务器收到客户端消息时会执行该方法
	 */
	@Override
	public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
		System.out.println("服务器收到客户端消息,消息内容:" + message.getPayload());
		String messageInfo = message.getPayload().toString();

		ChatMessage chatMessage = JSONUtil.toBean(JSONUtil.parseObj(messageInfo), ChatMessage.class);
		Date date = new Date();
		String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
		chatMessage.setTime(time);

		String form = JSONUtil.parseObj(messageInfo).getStr("form");
		String userId = null;
		String adminId = null;
		System.out.println(form);
		if (stringRedisTemplate.hasKey(RedisKey.USER_REFRESH_TOKEN_KEY(form))){
			System.out.println("用户");
			userId = tokenUtil.getUserId(form).toString();
			chatMessage.setForm(userId);
			chatMessage.setFormType("user");
			Set<Integer> userIds = new HashSet<>();
			userIds.add(Integer.parseInt(userId));
		} else {
			System.out.println("管理员");
			adminId = tokenUtil.getAdminId(form).toString();
			chatMessage.setForm(adminId);
			chatMessage.setFormType("admin");
			Set<Integer> adminIds = new HashSet<>();
			adminIds.add(Integer.parseInt(adminId));
		}

		String to = JSONUtil.parseObj(messageInfo).getStr("to");

		//为用户随机分配客服
		if (userId != null && (to == null || to.isEmpty())) {
			//判断用户对应的用户列表是否存在不存在随机分配客服，存在则发送给第一位客服
			if (stringRedisTemplate.hasKey(RedisKey.TALK_FORM_USER_KEY(userId))){
				//获取第一位客服
				to = stringRedisTemplate.opsForZSet().range(RedisKey.TALK_FORM_USER_KEY(userId), 0, 0).iterator().next();
				System.out.println("之前客服id:"+to);
			}else{
				Integer customerServiceId = permissionClient.getCustomerService(Integer.valueOf(userId)).getData();
				System.out.println("随机客服id:"+customerServiceId);
				to = customerServiceId.toString();
				if (to.equals(String.valueOf(0))) {
					throw new ZsdException("当前没有客服在线", 500);
				}
			}
		}

		System.out.println("userId:" + userId);
		System.out.println("adminId:" + adminId);

		//判断是否为客服
		if (adminId != null){
			Set<Integer> adminIds = new HashSet<>();
			adminIds.add(Integer.parseInt(adminId));
			//通过管理员ID获取管理员信息
			if (permissionClient.selectAdminInfoByIds(adminIds).getData().get(0).getRole() != 4) {
				throw new ZsdException("该用户不为客服无法通信", 500);
			}
		}

		if (userId!=null) {
			adminId = to;
            Set<Integer> adminIds = new HashSet<>();
            adminIds.add(Integer.parseInt(adminId));
            //通过管理员ID获取管理员信息
        } else {
			userId = to;
            Set<Integer> userIds = new HashSet<>();
            userIds.add(Integer.parseInt(userId));

        }
		//通过收信人ID获取收信session对象
		WebSocketSession toSession = sessions.get(to);
		System.out.println("toSession" + toSession);

		if( toSession != null && toSession.isOpen()){
			//将消息发送给收信人
			System.out.println("发送给用户:"+toSession);
			toSession.sendMessage(new TextMessage(JSONUtil.parseObj(chatMessage).toString()));
		} else {
			//将消息发送给离线用户
			//TODO
			//接收方不在线，存储未读消息
			System.out.println("发送给离线用户");
		}
		//存储当前角色聊天对象
		String formUserKey = RedisKey.TALK_FORM_USER_KEY(userId);
		String formAdminKey = RedisKey.TALK_FORM_ADMIN_KEY(adminId);

		stringRedisTemplate.opsForZSet().add(formUserKey, adminId, date.getTime());
		stringRedisTemplate.opsForZSet().add(formAdminKey, userId, date.getTime());

		//聊天记录存储
		String adminUserKey = RedisKey.TALK_ADMIN_USER_KEY(userId, adminId);
		String userAdminKey = RedisKey.TALK_USER_ADMIN_KEY(userId, adminId);

		stringRedisTemplate.opsForZSet().add(adminUserKey, JSONUtil.parseObj(chatMessage).toString(), date.getTime());
		stringRedisTemplate.opsForZSet().add(userAdminKey, JSONUtil.parseObj(chatMessage).toString(), date.getTime());
	}

	@Override
	public boolean supportsPartialMessages() {
		// TODO Auto-generated method stub
		return false;
	}
}